#include "stdafx.h"
#include "Emu/Memory/Memory.h"
#include "ARMv7Thread.h"
#include "ARMv7Interpreter.h"
#include "ARMv7Opcodes.h"
#include "ARMv7Decoder.h"

struct ARMv7_opcode_t
{
	u32 mask;
	u32 code;
	u32 length; // 2 or 4
	const char* name;
	ARMv7_encoding type;
	void(*func)(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type);
	bool(*skip)(u32 code);
};

// single 16-bit value
#define ARMv7_OP2(mask, code, type, name, ...) { (u32)((mask) << 16), (u32)((code) << 16), 2, #name "_" #type, type, ARMv7_instrs::name, __VA_ARGS__ }
// two 16-bit values
#define ARMv7_OP4(mask0, mask1, code0, code1, type, name, ...) { (u32)((mask0) << 16) | (mask1), (u32)((code0) << 16) | (code1), 4, #name "_" #type, type, ARMv7_instrs::name, __VA_ARGS__ }

#define SKIP_IF(cond) [](u32 c) -> bool { return cond; }

#define BF(start, end) ((c << (31 - (end))) >> ((start) + 31 - (end)))
#define BT(pos) ((c >> (pos)) & 1)

const ARMv7_opcode_t ARMv7_opcode_table[] =
{
	ARMv7_OP4(0xffff, 0x0000, 0xf870, 0x0000, T1, HACK, nullptr), // "Undefined" Thumb opcode used
	ARMv7_OP4(0x0ff0, 0x00f0, 0x0070, 0x0090, A1, HACK), // "Undefined" ARM opcode used

	ARMv7_OP4(0xfbe0, 0x8000, 0xf140, 0x0000, T1, ADC_IMM, nullptr),
	ARMv7_OP4(0x0fe0, 0x0000, 0x02a0, 0x0000, A1, ADC_IMM),
	ARMv7_OP2(0xffc0, 0x4140, T1, ADC_REG, nullptr),
	ARMv7_OP4(0xffe0, 0x8000, 0xeb40, 0x0000, T2, ADC_REG, nullptr),
	ARMv7_OP4(0x0fe0, 0x0010, 0x00a0, 0x0000, A1, ADC_REG),
	ARMv7_OP4(0x0fe0, 0x0090, 0x00a0, 0x0010, A1, ADC_RSR),

	ARMv7_OP2(0xfe00, 0x1c00, T1, ADD_IMM, nullptr),
	ARMv7_OP2(0xf800, 0x3000, T2, ADD_IMM, nullptr),
	ARMv7_OP4(0xfbe0, 0x8000, 0xf100, 0x0000, T3, ADD_IMM, SKIP_IF( (BF(8, 11) == 15 && BT(20)) || BF(16, 19) == 13 )),
	ARMv7_OP4(0xfbf0, 0x8000, 0xf200, 0x0000, T4, ADD_IMM, SKIP_IF( (BF(16, 19) & 13) == 13 )),
	ARMv7_OP4(0x0fe0, 0x0000, 0x0280, 0x0000, A1, ADD_IMM),
	ARMv7_OP2(0xfe00, 0x1800, T1, ADD_REG, nullptr),
	ARMv7_OP2(0xff00, 0x4400, T2, ADD_REG, SKIP_IF( (c & 0x87) == 0x85 || BF(3, 6) == 13 )),
	ARMv7_OP4(0xffe0, 0x8000, 0xeb00, 0x0000, T3, ADD_REG, SKIP_IF( (BF(8, 11) == 15 && BT(20)) || BF(16, 19) == 13 )),
	ARMv7_OP4(0x0fe0, 0x0010, 0x0080, 0x0000, A1, ADD_REG),
	ARMv7_OP4(0x0fe0, 0x0090, 0x0080, 0x0010, A1, ADD_RSR),
	ARMv7_OP2(0xf800, 0xa800, T1, ADD_SPI, nullptr),
	ARMv7_OP2(0xff80, 0xb000, T2, ADD_SPI, nullptr),
	ARMv7_OP4(0xfbef, 0x8000, 0xf10d, 0x0000, T3, ADD_SPI, SKIP_IF( BF(8, 11) == 15 && BT(20) )),
	ARMv7_OP4(0xfbff, 0x8000, 0xf20d, 0x0000, T4, ADD_SPI, nullptr),
	ARMv7_OP4(0x0fef, 0x0000, 0x028d, 0x0000, A1, ADD_SPI),
	ARMv7_OP2(0xff78, 0x4468, T1, ADD_SPR, nullptr),
	ARMv7_OP2(0xff87, 0x4485, T2, ADD_SPR, SKIP_IF( BF(3, 6) == 13 )),
	ARMv7_OP4(0xffef, 0x8000, 0xeb0d, 0x0000, T3, ADD_SPR, nullptr),
	ARMv7_OP4(0x0fef, 0x0010, 0x008d, 0x0000, A1, ADD_SPR),

	ARMv7_OP2(0xf800, 0xa000, T1, ADR, nullptr),
	ARMv7_OP4(0xfbff, 0x8000, 0xf2af, 0x0000, T2, ADR, nullptr),
	ARMv7_OP4(0xfbff, 0x8000, 0xf20f, 0x0000, T3, ADR, nullptr),
	ARMv7_OP4(0x0fff, 0x0000, 0x028f, 0x0000, A1, ADR),
	ARMv7_OP4(0x0fff, 0x0000, 0x024f, 0x0000, A2, ADR),

	ARMv7_OP4(0xfbe0, 0x8000, 0xf000, 0x0000, T1, AND_IMM, SKIP_IF( BF(8, 11) == 15 && BT(20) )),
	ARMv7_OP4(0x0fe0, 0x0000, 0x0200, 0x0000, A1, AND_IMM),
	ARMv7_OP2(0xffc0, 0x4000, T1, AND_REG, nullptr),
	ARMv7_OP4(0xffe0, 0x8000, 0xea00, 0x0000, T2, AND_REG, SKIP_IF( BF(8, 11) == 15 && BT(20) )),
	ARMv7_OP4(0x0fe0, 0x0010, 0x0000, 0x0000, A1, AND_REG),
	ARMv7_OP4(0x0fe0, 0x0090, 0x0000, 0x0010, A1, AND_RSR),

	ARMv7_OP2(0xf800, 0x1000, T1, ASR_IMM, nullptr),
	ARMv7_OP4(0xffef, 0x8030, 0xea4f, 0x0020, T2, ASR_IMM, nullptr),
	ARMv7_OP4(0x0fef, 0x0070, 0x01a0, 0x0040, A1, ASR_IMM),
	ARMv7_OP2(0xffc0, 0x4100, T1, ASR_REG, nullptr),
	ARMv7_OP4(0xffe0, 0xf0f0, 0xfa40, 0xf000, T2, ASR_REG, nullptr),
	ARMv7_OP4(0x0fef, 0x00f0, 0x01a0, 0x0050, A1, ASR_REG),

	ARMv7_OP2(0xf000, 0xd000, T1, B, SKIP_IF( BF(9, 11) == 0x7 )),
	ARMv7_OP2(0xf800, 0xe000, T2, B, nullptr),
	ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x8000, T3, B, SKIP_IF( BF(23, 25) == 0x7 )),
	ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x9000, T4, B, nullptr),
	ARMv7_OP4(0x0f00, 0x0000, 0x0a00, 0x0000, A1, B),

	ARMv7_OP4(0xffff, 0x8020, 0xf36f, 0x0000, T1, BFC, nullptr),
	ARMv7_OP4(0x0fe0, 0x007f, 0x07c0, 0x001f, A1, BFC),

	ARMv7_OP4(0xfff0, 0x8020, 0xf360, 0x0000, T1, BFI, SKIP_IF( BF(16, 19) == 15 )),
	ARMv7_OP4(0x0fe0, 0x0070, 0x07c0, 0x0010, A1, BFI),

	ARMv7_OP4(0xfbe0, 0x8000, 0xf020, 0x0000, T1, BIC_IMM, nullptr),
	ARMv7_OP4(0x0fe0, 0x0000, 0x03c0, 0x0000, A1, BIC_IMM),
	ARMv7_OP2(0xffc0, 0x4380, T1, BIC_REG, nullptr),
	ARMv7_OP4(0xffe0, 0x8000, 0xea20, 0x0000, T2, BIC_REG, nullptr),
	ARMv7_OP4(0x0fe0, 0x0010, 0x01c0, 0x0000, A1, BIC_REG),
	ARMv7_OP4(0x0fe0, 0x0090, 0x01c0, 0x0010, A1, BIC_RSR),

	ARMv7_OP2(0xff00, 0xbe00, T1, BKPT, nullptr),
	ARMv7_OP4(0x0ff0, 0x00f0, 0x0120, 0x0070, A1, BKPT),

	ARMv7_OP4(0xf800, 0xd000, 0xf000, 0xd000, T1, BL, nullptr),
	ARMv7_OP4(0x0f00, 0x0000, 0x0b00, 0x0000, A1, BL),
	ARMv7_OP2(0xff80, 0x4780, T1, BLX, nullptr),
	ARMv7_OP4(0xf800, 0xc001, 0xf000, 0xc000, T2, BLX, nullptr),
	ARMv7_OP4(0x0fff, 0xfff0, 0x012f, 0xff30, A1, BLX),
	ARMv7_OP4(0xfe00, 0x0000, 0xfa00, 0x0000, A2, BLX),

	ARMv7_OP2(0xff87, 0x4700, T1, BX, nullptr),
	ARMv7_OP4(0x0fff, 0xfff0, 0x012f, 0xff10, A1, BX),

	ARMv7_OP2(0xf500, 0xb100, T1, CB_Z, nullptr),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfab0, 0xf080, T1, CLZ, nullptr),
	ARMv7_OP4(0x0fff, 0x0ff0, 0x016f, 0x0f10, A1, CLZ),

	ARMv7_OP4(0xfbf0, 0x8f00, 0xf110, 0x0f00, T1, CMN_IMM, nullptr),
	ARMv7_OP4(0x0ff0, 0xf000, 0x0370, 0x0000, A1, CMN_IMM),
	ARMv7_OP2(0xffc0, 0x42c0, T1, CMN_REG, nullptr),
	ARMv7_OP4(0xfff0, 0x8f00, 0xeb10, 0x0f00, T2, CMN_REG, nullptr),
	ARMv7_OP4(0x0ff0, 0xf010, 0x0170, 0x0000, A1, CMN_REG),
	ARMv7_OP4(0x0ff0, 0xf090, 0x0170, 0x0010, A1, CMN_RSR),

	ARMv7_OP2(0xf800, 0x2800, T1, CMP_IMM, nullptr),
	ARMv7_OP4(0xfbf0, 0x8f00, 0xf1b0, 0x0f00, T2, CMP_IMM, nullptr),
	ARMv7_OP4(0x0ff0, 0xf000, 0x0350, 0x0000, A1, CMP_IMM),
	ARMv7_OP2(0xffc0, 0x4280, T1, CMP_REG, nullptr),
	ARMv7_OP2(0xff00, 0x4500, T2, CMP_REG, nullptr),
	ARMv7_OP4(0xfff0, 0x8f00, 0xebb0, 0x0f00, T3, CMP_REG, nullptr),
	ARMv7_OP4(0x0ff0, 0xf010, 0x0150, 0x0000, A1, CMP_REG),
	ARMv7_OP4(0x0ff0, 0xf090, 0x0150, 0x0010, A1, CMP_RSR),

	ARMv7_OP4(0xffff, 0xfff0, 0xf3af, 0x80f0, T1, DBG, nullptr),
	ARMv7_OP4(0x0fff, 0xfff0, 0x0320, 0xf0f0, A1, DBG),

	ARMv7_OP4(0xffff, 0xfff0, 0xf3bf, 0x8f50, T1, DMB, nullptr),
	ARMv7_OP4(0xffff, 0xfff0, 0xf57f, 0xf050, A1, DMB),

	ARMv7_OP4(0xffff, 0xfff0, 0xf3bf, 0x8f40, T1, DSB, nullptr),
	ARMv7_OP4(0xffff, 0xfff0, 0xf57f, 0xf040, A1, DSB),

	ARMv7_OP4(0xfbe0, 0x8000, 0xf080, 0x0000, T1, EOR_IMM, SKIP_IF( BF(8, 11) == 15 && BT(20) )),
	ARMv7_OP4(0x0fe0, 0x0000, 0x0220, 0x0000, A1, EOR_IMM),
	ARMv7_OP2(0xffc0, 0x4040, T1, EOR_REG, nullptr),
	ARMv7_OP4(0xffe0, 0x8000, 0xea80, 0x0000, T2, EOR_REG, SKIP_IF( BF(8, 11) == 15 && BT(20) )),
	ARMv7_OP4(0x0fe0, 0x0010, 0x0020, 0x0000, A1, EOR_REG),
	ARMv7_OP4(0x0fe0, 0x0090, 0x0020, 0x0010, A1, EOR_RSR),

	ARMv7_OP2(0xff00, 0xbf00, T1, IT, SKIP_IF( BF(0, 3) == 0 )),

	ARMv7_OP2(0xf800, 0xc800, T1, LDM, nullptr),
	ARMv7_OP4(0xffd0, 0x2000, 0xe890, 0x0000, T2, LDM, SKIP_IF( BT(21) && BF(16, 19) == 13 )),
	ARMv7_OP4(0x0fd0, 0x0000, 0x0890, 0x0000, A1, LDM),
	ARMv7_OP4(0x0fd0, 0x0000, 0x0810, 0x0000, A1, LDMDA),
	ARMv7_OP4(0xffd0, 0x2000, 0xe910, 0x0000, T1, LDMDB, nullptr),
	ARMv7_OP4(0x0fd0, 0x0000, 0x0910, 0x0000, A1, LDMDB),
	ARMv7_OP4(0x0fd0, 0x0000, 0x0990, 0x0000, A1, LDMIB),

	ARMv7_OP2(0xf800, 0x6800, T1, LDR_IMM, nullptr),
	ARMv7_OP2(0xf800, 0x9800, T2, LDR_IMM, nullptr),
	ARMv7_OP4(0xfff0, 0x0000, 0xf8d0, 0x0000, T3, LDR_IMM, SKIP_IF( BF(16, 19) == 15 )),
	ARMv7_OP4(0xfff0, 0x0800, 0xf850, 0x0800, T4, LDR_IMM, SKIP_IF( BF(16, 19) == 15 || BF(8, 10) == 6 || (c & 0xf07ff) == 0xd0304 || (c & 0x500) == 0 )),
	ARMv7_OP4(0x0e50, 0x0000, 0x0410, 0x0000, A1, LDR_IMM),
	ARMv7_OP2(0xf800, 0x4800, T1, LDR_LIT, nullptr),
	ARMv7_OP4(0xff7f, 0x0000, 0xf85f, 0x0000, T2, LDR_LIT, nullptr),
	ARMv7_OP4(0x0f7f, 0x0000, 0x051f, 0x0000, A1, LDR_LIT),
	ARMv7_OP2(0xfe00, 0x5800, T1, LDR_REG, nullptr),
	ARMv7_OP4(0xfff0, 0x0fc0, 0xf850, 0x0000, T2, LDR_REG, SKIP_IF( BF(16, 19) == 15 )),
	ARMv7_OP4(0x0e50, 0x0010, 0x0610, 0x0000, A1, LDR_REG),
	
	ARMv7_OP2(0xf800, 0x7800, T1, LDRB_IMM),
	ARMv7_OP4(0xfff0, 0x0000, 0xf890, 0x0000, T2, LDRB_IMM),
	ARMv7_OP4(0xfff0, 0x0800, 0xf810, 0x0800, T3, LDRB_IMM),
	ARMv7_OP4(0x0e50, 0x0000, 0x0450, 0x0000, A1, LDRB_IMM),
	ARMv7_OP4(0xff7f, 0x0000, 0xf81f, 0x0000, T1, LDRB_LIT),
	ARMv7_OP4(0x0f7f, 0x0000, 0x055f, 0x0000, A1, LDRB_LIT),
	ARMv7_OP2(0xfe00, 0x5c00, T1, LDRB_REG),
	ARMv7_OP4(0xfff0, 0x0fc0, 0xf810, 0x0000, T2, LDRB_REG),
	ARMv7_OP4(0x0e50, 0x0010, 0x0650, 0x0000, A1, LDRB_REG),

	ARMv7_OP4(0xfe50, 0x0000, 0xe850, 0x0000, T1, LDRD_IMM, SKIP_IF( (!BT(21) && !BT(24)) || BF(16, 19) == 15 )),
	ARMv7_OP4(0x0e50, 0x00f0, 0x0040, 0x00d0, A1, LDRD_IMM),
	ARMv7_OP4(0xfe7f, 0x0000, 0xe85f, 0x0000, T1, LDRD_LIT),
	ARMv7_OP4(0x0f7f, 0x00f0, 0x014f, 0x00d0, A1, LDRD_LIT),
	ARMv7_OP4(0x0e50, 0x0ff0, 0x0000, 0x00d0, A1, LDRD_REG),

	ARMv7_OP4(0xfff0, 0x0f00, 0xe850, 0x0f00, T1, LDREX),
	ARMv7_OP4(0x0ff0, 0x0fff, 0x0190, 0x0f9f, A1, LDREX),
	ARMv7_OP4(0xfff0, 0x0fff, 0xe8d0, 0x0f4f, T1, LDREXB),
	ARMv7_OP4(0x0ff0, 0x0fff, 0x01d0, 0x0f9f, A1, LDREXB),
	ARMv7_OP4(0xfff0, 0x00ff, 0xe8d0, 0x007f, T1, LDREXD),
	ARMv7_OP4(0x0ff0, 0x0fff, 0x01b0, 0x0f9f, A1, LDREXD),
	ARMv7_OP4(0xfff0, 0x0fff, 0xe8d0, 0x0f5f, T1, LDREXH),
	ARMv7_OP4(0x0ff0, 0x0fff, 0x01f0, 0x0f9f, A1, LDREXH),

	ARMv7_OP2(0xf800, 0x8800, T1, LDRH_IMM),
	ARMv7_OP4(0xfff0, 0x0000, 0xf8b0, 0x0000, T2, LDRH_IMM),
	ARMv7_OP4(0xfff0, 0x0800, 0xf830, 0x0800, T3, LDRH_IMM),
	ARMv7_OP4(0x0e50, 0x00f0, 0x0050, 0x00b0, A1, LDRH_IMM),
	ARMv7_OP4(0xff7f, 0x0000, 0xf83f, 0x0000, T1, LDRH_LIT),
	ARMv7_OP4(0x0f7f, 0x00f0, 0x015f, 0x00b0, A1, LDRH_LIT),
	ARMv7_OP2(0xfe00, 0x5a00, T1, LDRH_REG),
	ARMv7_OP4(0xfff0, 0x0fc0, 0xf830, 0x0000, T2, LDRH_REG),
	ARMv7_OP4(0x0e50, 0x0ff0, 0x0010, 0x00b0, A1, LDRH_REG),

	ARMv7_OP4(0xfff0, 0x0000, 0xf990, 0x0000, T1, LDRSB_IMM),
	ARMv7_OP4(0xfff0, 0x0800, 0xf910, 0x0800, T2, LDRSB_IMM),
	ARMv7_OP4(0x0e50, 0x00f0, 0x0050, 0x00d0, A1, LDRSB_IMM),
	ARMv7_OP4(0xff7f, 0x0000, 0xf91f, 0x0000, T1, LDRSB_LIT),
	ARMv7_OP4(0x0f7f, 0x00f0, 0x015f, 0x00d0, A1, LDRSB_LIT),
	ARMv7_OP2(0xfe00, 0x5600, T1, LDRSB_REG),
	ARMv7_OP4(0xfff0, 0x0fc0, 0xf910, 0x0000, T2, LDRSB_REG),
	ARMv7_OP4(0x0e50, 0x0ff0, 0x0010, 0x00d0, A1, LDRSB_REG),

	ARMv7_OP4(0xfff0, 0x0000, 0xf9b0, 0x0000, T1, LDRSH_IMM),
	ARMv7_OP4(0xfff0, 0x0800, 0xf930, 0x0800, T2, LDRSH_IMM),
	ARMv7_OP4(0x0e50, 0x00f0, 0x0050, 0x00f0, A1, LDRSH_IMM),
	ARMv7_OP4(0xff7f, 0x0000, 0xf93f, 0x0000, T1, LDRSH_LIT),
	ARMv7_OP4(0x0f7f, 0x00f0, 0x015f, 0x00f0, A1, LDRSH_LIT),
	ARMv7_OP2(0xfe00, 0x5e00, T1, LDRSH_REG),
	ARMv7_OP4(0xfff0, 0x0fc0, 0xf930, 0x0000, T2, LDRSH_REG),
	ARMv7_OP4(0x0e50, 0x0ff0, 0x0010, 0x00f0, A1, LDRSH_REG),

	ARMv7_OP2(0xf800, 0x0000, T1, LSL_IMM),
	ARMv7_OP4(0xffef, 0x8030, 0xea4f, 0x0000, T2, LSL_IMM),
	ARMv7_OP4(0x0fef, 0x0070, 0x01a0, 0x0000, A1, LSL_IMM),
	ARMv7_OP2(0xffc0, 0x4080, T1, LSL_REG),
	ARMv7_OP4(0xffe0, 0xf0f0, 0xfa00, 0xf000, T2, LSL_REG),
	ARMv7_OP4(0x0fef, 0x00f0, 0x01a0, 0x0010, A1, LSL_REG),

	ARMv7_OP2(0xf800, 0x0800, T1, LSR_IMM),
	ARMv7_OP4(0xffef, 0x8030, 0xea4f, 0x0010, T2, LSR_IMM),
	ARMv7_OP4(0x0fef, 0x0030, 0x01a0, 0x0020, A1, LSR_IMM),
	ARMv7_OP2(0xffc0, 0x40c0, T1, LSR_REG),
	ARMv7_OP4(0xffe0, 0xf0f0, 0xfa20, 0xf000, T2, LSR_REG),
	ARMv7_OP4(0x0fef, 0x00f0, 0x01a0, 0x0030, A1, LSR_REG),

	ARMv7_OP4(0xfff0, 0x00f0, 0xfb00, 0x0000, T1, MLA, SKIP_IF( BF(12, 15) == 15 )),
	ARMv7_OP4(0x0fe0, 0x00f0, 0x0020, 0x0090, A1, MLA),

	ARMv7_OP4(0xfff0, 0x00f0, 0xfb00, 0x0010, T1, MLS),
	ARMv7_OP4(0x0ff0, 0x00f0, 0x0060, 0x0090, A1, MLS),

	ARMv7_OP2(0xf800, 0x2000, T1, MOV_IMM),
	ARMv7_OP4(0xfbef, 0x8000, 0xf04f, 0x0000, T2, MOV_IMM),
	ARMv7_OP4(0xfbf0, 0x8000, 0xf240, 0x0000, T3, MOV_IMM),
	ARMv7_OP4(0x0fef, 0x0000, 0x03a0, 0x0000, A1, MOV_IMM),
	ARMv7_OP4(0x0ff0, 0x0000, 0x0300, 0x0000, A2, MOV_IMM),
	ARMv7_OP2(0xff00, 0x4600, T1, MOV_REG),
	ARMv7_OP2(0xffc0, 0x0000, T2, MOV_REG),
	ARMv7_OP4(0xffef, 0xf0f0, 0xea4f, 0x0000, T3, MOV_REG),
	ARMv7_OP4(0x0fef, 0x0ff0, 0x01a0, 0x0000, A1, MOV_REG),

	ARMv7_OP4(0xfbf0, 0x8000, 0xf2c0, 0x0000, T1, MOVT),
	ARMv7_OP4(0x0ff0, 0x0000, 0x0340, 0x0000, A1, MOVT),

	ARMv7_OP4(0xff10, 0x0010, 0xee10, 0x0010, T1, MRC_),
	ARMv7_OP4(0x0f10, 0x0010, 0x0e10, 0x0010, A1, MRC_),
	ARMv7_OP4(0xff10, 0x0010, 0xfe10, 0x0010, T2, MRC_),
	ARMv7_OP4(0xff10, 0x0010, 0xfe10, 0x0010, A2, MRC_),

	ARMv7_OP4(0xffff, 0xf0ff, 0xf3ef, 0x8000, T1, MRS),
	ARMv7_OP4(0x0fff, 0x0fff, 0x010f, 0x0000, A1, MRS),

	ARMv7_OP4(0x0ff3, 0xf000, 0x0320, 0xf000, A1, MSR_IMM),
	ARMv7_OP4(0xfff0, 0xf3ff, 0xf380, 0x8000, T1, MSR_REG),
	ARMv7_OP4(0x0ff3, 0xfff0, 0x0120, 0xf000, A1, MSR_REG),

	ARMv7_OP2(0xffc0, 0x4340, T1, MUL),
	ARMv7_OP4(0xfff0, 0xf0f0, 0xfb00, 0xf000, T2, MUL),
	ARMv7_OP4(0x0fe0, 0xf0f0, 0x0000, 0x0090, A1, MUL),

	ARMv7_OP4(0xfbef, 0x8000, 0xf06f, 0x0000, T1, MVN_IMM),
	ARMv7_OP4(0x0fef, 0x0000, 0x03e0, 0x0000, A1, MVN_IMM),
	ARMv7_OP2(0xffc0, 0x43c0, T1, MVN_REG),
	ARMv7_OP4(0xffef, 0x8000, 0xea6f, 0x0000, T2, MVN_REG),
	ARMv7_OP4(0xffef, 0x0010, 0x01e0, 0x0000, A1, MVN_REG),
	ARMv7_OP4(0x0fef, 0x0090, 0x01e0, 0x0010, A1, MVN_RSR),

	ARMv7_OP2(0xffff, 0xbf00, T1, NOP),
	ARMv7_OP4(0xffff, 0xffff, 0xf3af, 0x8000, T2, NOP),
	ARMv7_OP4(0x0fff, 0xffff, 0x0320, 0xf000, A1, NOP),

	ARMv7_OP4(0xfbe0, 0x8000, 0xf060, 0x0000, T1, ORN_IMM),
	ARMv7_OP4(0xffe0, 0x8000, 0xea60, 0x0000, T1, ORN_REG),

	ARMv7_OP4(0xfbe0, 0x8000, 0xf040, 0x0000, T1, ORR_IMM),
	ARMv7_OP4(0x0fe0, 0x0000, 0x0380, 0x0000, A1, ORR_IMM),
	ARMv7_OP2(0xffc0, 0x4300, T1, ORR_REG),
	ARMv7_OP4(0xffe0, 0x8000, 0xea40, 0x0000, T2, ORR_REG, SKIP_IF( BF(16, 19) == 15 )),
	ARMv7_OP4(0x0fe0, 0x0010, 0x0180, 0x0000, A1, ORR_REG),
	ARMv7_OP4(0x0fe0, 0x0090, 0x0180, 0x0010, A1, ORR_RSR),

	ARMv7_OP4(0xfff0, 0x8010, 0xeac0, 0x0000, T1, PKH),
	ARMv7_OP4(0x0ff0, 0x0030, 0x0680, 0x0010, A1, PKH),

	ARMv7_OP2(0xfe00, 0xbc00, T1, POP),
	ARMv7_OP4(0xffff, 0x0000, 0xe8bd, 0x0000, T2, POP),
	ARMv7_OP4(0xffff, 0x0fff, 0xf85d, 0x0b04, T3, POP),
	ARMv7_OP4(0x0fff, 0x0000, 0x08bd, 0x0000, A1, POP),
	ARMv7_OP4(0x0fff, 0x0fff, 0x049d, 0x0004, A2, POP),

	ARMv7_OP2(0xfe00, 0xb400, T1, PUSH),
	ARMv7_OP4(0xffff, 0x0000, 0xe92d, 0x0000, T2, PUSH), // had an error in arch ref
	ARMv7_OP4(0xffff, 0x0fff, 0xf84d, 0x0d04, T3, PUSH),
	ARMv7_OP4(0x0fff, 0x0000, 0x092d, 0x0000, A1, PUSH),
	ARMv7_OP4(0x0fff, 0x0fff, 0x052d, 0x0004, A2, PUSH),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfa80, 0xf080, T1, QADD),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0100, 0x0050, A1, QADD),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfa90, 0xf010, T1, QADD16),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0620, 0x0f10, A1, QADD16),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfa80, 0xf010, T1, QADD8),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0620, 0x0f90, A1, QADD8),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfaa0, 0xf010, T1, QASX),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0620, 0x0f30, A1, QASX),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfa80, 0xf090, T1, QDADD),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0140, 0x0050, A1, QDADD),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfa80, 0xf0b0, T1, QDSUB),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0160, 0x0050, A1, QDSUB),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfae0, 0xf010, T1, QSAX),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0620, 0x0f50, A1, QSAX),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfa80, 0xf0a0, T1, QSUB),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0120, 0x0050, A1, QSUB),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfad0, 0xf010, T1, QSUB16),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0620, 0x0f70, A1, QSUB16),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfac0, 0xf010, T1, QSUB8),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0620, 0x0ff0, A1, QSUB8),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfa90, 0xf0a0, T1, RBIT),
	ARMv7_OP4(0x0fff, 0x0ff0, 0x06ff, 0x0f30, A1, RBIT),

	ARMv7_OP2(0xffc0, 0xba00, T1, REV),
	ARMv7_OP4(0xfff0, 0xf0f0, 0xfa90, 0xf080, T2, REV),
	ARMv7_OP4(0x0fff, 0x0ff0, 0x06bf, 0x0f30, A1, REV),

	ARMv7_OP2(0xffc0, 0xba40, T1, REV16),
	ARMv7_OP4(0xfff0, 0xf0f0, 0xfa90, 0xf090, T2, REV16),
	ARMv7_OP4(0x0fff, 0x0ff0, 0x06bf, 0x0fb0, A1, REV16),

	ARMv7_OP2(0xffc0, 0xbac0, T1, REVSH),
	ARMv7_OP4(0xfff0, 0xf0f0, 0xfa90, 0xf0b0, T2, REVSH),
	ARMv7_OP4(0x0fff, 0x0ff0, 0x06ff, 0x0fb0, A1, REVSH),

	ARMv7_OP4(0xffef, 0x8030, 0xea4f, 0x0030, T1, ROR_IMM),
	ARMv7_OP4(0x0fef, 0x0070, 0x01a0, 0x0060, A1, ROR_IMM),
	ARMv7_OP2(0xffc0, 0x41c0, T1, ROR_REG),
	ARMv7_OP4(0xffe0, 0xf0f0, 0xfa60, 0xf000, T2, ROR_REG),
	ARMv7_OP4(0x0fef, 0x00f0, 0x01a0, 0x0070, A1, ROR_REG),
	ARMv7_OP4(0xffef, 0xf0f0, 0xea4f, 0x0030, T1, RRX),
	ARMv7_OP4(0x0fef, 0x0ff0, 0x01a0, 0x0060, A1, RRX),

	ARMv7_OP2(0xffc0, 0x4240, T1, RSB_IMM),
	ARMv7_OP4(0xfbe0, 0x8000, 0xf1c0, 0x0000, T2, RSB_IMM),
	ARMv7_OP4(0x0fe0, 0x0000, 0x0260, 0x0000, A1, RSB_IMM),
	ARMv7_OP4(0xffe0, 0x8000, 0xebc0, 0x0000, T1, RSB_REG),
	ARMv7_OP4(0x0fe0, 0x0010, 0x0060, 0x0000, A1, RSB_REG),
	ARMv7_OP4(0x0fe0, 0x0090, 0x0060, 0x0010, A1, RSB_RSR),

	ARMv7_OP4(0x0fe0, 0x0000, 0x02e0, 0x0000, A1, RSC_IMM),
	ARMv7_OP4(0x0fe0, 0x0010, 0x00e0, 0x0000, A1, RSC_REG),
	ARMv7_OP4(0x0fe0, 0x0090, 0x00e0, 0x0010, A1, RSC_RSR),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfa90, 0xf000, T1, SADD16),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0610, 0x0f10, A1, SADD16),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfa80, 0xf000, T1, SADD8),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0610, 0x0f90, A1, SADD8),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfaa0, 0xf000, T1, SASX),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0610, 0x0f30, A1, SASX),

	ARMv7_OP4(0xfbe0, 0x8000, 0xf160, 0x0000, T1, SBC_IMM),
	ARMv7_OP4(0x0fe0, 0x0000, 0x02c0, 0x0000, A1, SBC_IMM),
	ARMv7_OP2(0xffc0, 0x4180, T1, SBC_REG),
	ARMv7_OP4(0xffe0, 0x8000, 0xeb60, 0x0000, T2, SBC_REG),
	ARMv7_OP4(0x0fe0, 0x0010, 0x00c0, 0x0000, A1, SBC_REG),
	ARMv7_OP4(0x0fe0, 0x0090, 0x00c0, 0x0010, A1, SBC_RSR),

	ARMv7_OP4(0xfff0, 0x8020, 0xf340, 0x0000, T1, SBFX),
	ARMv7_OP4(0x0fe0, 0x0070, 0x07a0, 0x0050, A1, SBFX),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfb90, 0xf0f0, T1, SDIV), // ???

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfaa0, 0xf080, T1, SEL),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0680, 0x0fb0, A1, SEL),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfa90, 0xf020, T1, SHADD16),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0630, 0x0f10, A1, SHADD16),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfa80, 0xf020, T1, SHADD8),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0630, 0x0f90, A1, SHADD8),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfaa0, 0xf020, T1, SHASX),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0630, 0x0f30, A1, SHASX),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfae0, 0xf020, T1, SHSAX),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0630, 0x0f50, A1, SHSAX),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfad0, 0xf020, T1, SHSUB16),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0630, 0x0f70, A1, SHSUB16),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfac0, 0xf020, T1, SHSUB8),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0630, 0x0ff0, A1, SHSUB8),

	ARMv7_OP4(0xfff0, 0x00c0, 0xfb10, 0x0000, T1, SMLA__),
	ARMv7_OP4(0x0ff0, 0x0090, 0x0100, 0x0080, A1, SMLA__),

	ARMv7_OP4(0xfff0, 0x00e0, 0xfb20, 0x0000, T1, SMLAD),
	ARMv7_OP4(0x0ff0, 0x00d0, 0x0700, 0x0010, A1, SMLAD),

	ARMv7_OP4(0xfff0, 0x00f0, 0xfbc0, 0x0000, T1, SMLAL),
	ARMv7_OP4(0x0fe0, 0x00f0, 0x00e0, 0x0090, A1, SMLAL),

	ARMv7_OP4(0xfff0, 0x00c0, 0xfbc0, 0x0080, T1, SMLAL__),
	ARMv7_OP4(0x0ff0, 0x0090, 0x0140, 0x0080, A1, SMLAL__),

	ARMv7_OP4(0xfff0, 0x00e0, 0xfbc0, 0x00c0, T1, SMLALD),
	ARMv7_OP4(0x0ff0, 0x00d0, 0x0740, 0x0010, A1, SMLALD),

	ARMv7_OP4(0xfff0, 0x00e0, 0xfb30, 0x0000, T1, SMLAW_),
	ARMv7_OP4(0x0ff0, 0x00b0, 0x0120, 0x0080, A1, SMLAW_),

	ARMv7_OP4(0xfff0, 0x00e0, 0xfb40, 0x0000, T1, SMLSD),
	ARMv7_OP4(0x0ff0, 0x00d0, 0x0700, 0x0050, A1, SMLSD),

	ARMv7_OP4(0xfff0, 0x00e0, 0xfbd0, 0x00c0, T1, SMLSLD),
	ARMv7_OP4(0x0ff0, 0x00d0, 0x0740, 0x0050, A1, SMLSLD),

	ARMv7_OP4(0xfff0, 0x00e0, 0xfb50, 0x0000, T1, SMMLA),
	ARMv7_OP4(0x0ff0, 0x00d0, 0x0750, 0x0010, A1, SMMLA),

	ARMv7_OP4(0xfff0, 0x00e0, 0xfb60, 0x0000, T1, SMMLS),
	ARMv7_OP4(0x0ff0, 0x00d0, 0x0750, 0x00d0, A1, SMMLS),

	ARMv7_OP4(0xfff0, 0xf0e0, 0xfb50, 0xf000, T1, SMMUL),
	ARMv7_OP4(0x0ff0, 0xf0d0, 0x0750, 0xf010, A1, SMMUL),

	ARMv7_OP4(0xfff0, 0xf0e0, 0xfb20, 0xf000, T1, SMUAD),
	ARMv7_OP4(0x0ff0, 0xf0d0, 0x0700, 0xf010, A1, SMUAD),

	ARMv7_OP4(0xfff0, 0xf0c0, 0xfb10, 0xf000, T1, SMUL__),
	ARMv7_OP4(0x0ff0, 0xf090, 0x0160, 0x0080, A1, SMUL__),

	ARMv7_OP4(0xfff0, 0x00f0, 0xfb80, 0x0000, T1, SMULL),
	ARMv7_OP4(0x0fe0, 0x00f0, 0x00c0, 0x0090, A1, SMULL),

	ARMv7_OP4(0xfff0, 0xf0e0, 0xfb30, 0xf000, T1, SMULW_),
	ARMv7_OP4(0x0ff0, 0xf0b0, 0x0120, 0x00a0, A1, SMULW_),

	ARMv7_OP4(0xfff0, 0xf0e0, 0xfb40, 0xf000, T1, SMUSD),
	ARMv7_OP4(0x0ff0, 0xf0d0, 0x0700, 0xf050, A1, SMUSD),

	ARMv7_OP4(0xffd0, 0x8020, 0xf300, 0x0000, T1, SSAT),
	ARMv7_OP4(0x0fe0, 0x0030, 0x06a0, 0x0010, A1, SSAT),

	ARMv7_OP4(0xfff0, 0xf0e0, 0xf320, 0x0000, T1, SSAT16),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x06a0, 0x0f30, A1, SSAT16),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfae0, 0xf000, T1, SSAX),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0610, 0x0f50, A1, SSAX),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfad0, 0xf000, T1, SSUB16),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0610, 0x0f70, A1, SSUB16),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfac0, 0xf000, T1, SSUB8),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0610, 0x0ff0, A1, SSUB8),

	ARMv7_OP2(0xf800, 0xc000, T1, STM),
	ARMv7_OP4(0xffd0, 0xa000, 0xe880, 0x0000, T2, STM),
	ARMv7_OP4(0x0fd0, 0x0000, 0x0880, 0x0000, A1, STM),
	ARMv7_OP4(0x0fd0, 0x0000, 0x0800, 0x0000, A1, STMDA),
	ARMv7_OP4(0xffd0, 0xa000, 0xe900, 0x0000, T1, STMDB),
	ARMv7_OP4(0x0fd0, 0x0000, 0x0900, 0x0000, A1, STMDB),
	ARMv7_OP4(0x0fd0, 0x0000, 0x0980, 0x0000, A1, STMIB),

	ARMv7_OP2(0xf800, 0x6000, T1, STR_IMM),
	ARMv7_OP2(0xf800, 0x9000, T2, STR_IMM),
	ARMv7_OP4(0xfff0, 0x0000, 0xf8c0, 0x0000, T3, STR_IMM),
	ARMv7_OP4(0xfff0, 0x0800, 0xf840, 0x0800, T4, STR_IMM),
	ARMv7_OP4(0x0e50, 0x0000, 0x0400, 0x0000, A1, STR_IMM),
	ARMv7_OP2(0xfe00, 0x5000, T1, STR_REG),
	ARMv7_OP4(0xfff0, 0x0fc0, 0xf840, 0x0000, T2, STR_REG),
	ARMv7_OP4(0x0e50, 0x0010, 0x0600, 0x0000, A1, STR_REG),

	ARMv7_OP2(0xf800, 0x7000, T1, STRB_IMM),
	ARMv7_OP4(0xfff0, 0x0000, 0xf880, 0x0000, T2, STRB_IMM),
	ARMv7_OP4(0xfff0, 0x0800, 0xf800, 0x0800, T3, STRB_IMM),
	ARMv7_OP4(0x0e50, 0x0000, 0x0440, 0x0000, A1, STRB_IMM),
	ARMv7_OP2(0xfe00, 0x5400, T1, STRB_REG),
	ARMv7_OP4(0xfff0, 0x0fc0, 0xf800, 0x0000, T2, STRB_REG),
	ARMv7_OP4(0x0e50, 0x0010, 0x0640, 0x0000, A1, STRB_REG),

	ARMv7_OP4(0xfe50, 0x0000, 0xe840, 0x0000, T1, STRD_IMM, SKIP_IF( !BT(21) && !BT(24) )),
	ARMv7_OP4(0x0e50, 0x00f0, 0x0040, 0x00f0, A1, STRD_IMM),
	ARMv7_OP4(0x0e50, 0x0ff0, 0x0000, 0x00f0, A1, STRD_REG),

	ARMv7_OP4(0xfff0, 0x0000, 0xe840, 0x0000, T1, STREX),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0180, 0x0f90, A1, STREX),
	ARMv7_OP4(0xfff0, 0x0ff0, 0xe8c0, 0x0f40, T1, STREXB),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x01c0, 0x0f90, A1, STREXB),
	ARMv7_OP4(0xfff0, 0x00f0, 0xe8c0, 0x0070, T1, STREXD),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x01a0, 0x0f90, A1, STREXD),
	ARMv7_OP4(0xfff0, 0x0ff0, 0xe8c0, 0x0f50, T1, STREXH),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x01e0, 0x0f90, A1, STREXH),

	ARMv7_OP2(0xf800, 0x8000, T1, STRH_IMM),
	ARMv7_OP4(0xfff0, 0x0000, 0xf8a0, 0x0000, T2, STRH_IMM),
	ARMv7_OP4(0xfff0, 0x0800, 0xf820, 0x0800, T3, STRH_IMM),
	ARMv7_OP4(0x0e50, 0x00f0, 0x0040, 0x00b0, A1, STRH_IMM),
	ARMv7_OP2(0xfe00, 0x5200, T1, STRH_REG),
	ARMv7_OP4(0xfff0, 0x0fc0, 0xf820, 0x0000, T2, STRH_REG),
	ARMv7_OP4(0x0e50, 0x0ff0, 0x0000, 0x00b0, A1, STRH_REG),

	ARMv7_OP2(0xfe00, 0x1e00, T1, SUB_IMM),
	ARMv7_OP2(0xf800, 0x3800, T2, SUB_IMM),
	ARMv7_OP4(0xfbe0, 0x8000, 0xf1a0, 0x0000, T3, SUB_IMM, SKIP_IF( (BF(8, 11) == 15 && BT(20)) || BF(16, 19) == 13 )),
	ARMv7_OP4(0xfbf0, 0x8000, 0xf2a0, 0x0000, T4, SUB_IMM),
	ARMv7_OP4(0x0fe0, 0x0000, 0x0240, 0x0000, A1, SUB_IMM),
	ARMv7_OP2(0xfe00, 0x1a00, T1, SUB_REG),
	ARMv7_OP4(0xffe0, 0x8000, 0xeba0, 0x0000, T2, SUB_REG, SKIP_IF( (BF(8, 11) == 15 && BT(20)) || BF(16, 19) == 13 )),
	ARMv7_OP4(0x0fe0, 0x0010, 0x0040, 0x0000, A1, SUB_REG),
	ARMv7_OP4(0x0fe0, 0x0090, 0x0040, 0x0010, A1, SUB_RSR),
	ARMv7_OP2(0xff80, 0xb080, T1, SUB_SPI),
	ARMv7_OP4(0xfbef, 0x8000, 0xf1ad, 0x0000, T2, SUB_SPI),
	ARMv7_OP4(0xfbff, 0x8000, 0xf2ad, 0x0000, T3, SUB_SPI),
	ARMv7_OP4(0x0fef, 0x0000, 0x024d, 0x0000, A1, SUB_SPI),
	ARMv7_OP4(0xffef, 0x8000, 0xebad, 0x0000, T1, SUB_SPR),
	ARMv7_OP4(0x0fef, 0x0010, 0x004d, 0x0000, A1, SUB_SPR),

	ARMv7_OP2(0xff00, 0xdf00, T1, SVC),
	ARMv7_OP4(0x0f00, 0x0000, 0x0f00, 0x0000, A1, SVC),

	ARMv7_OP4(0xfff0, 0xf0c0, 0xfa40, 0xf080, T1, SXTAB),
	ARMv7_OP4(0x0ff0, 0x03f0, 0x06a0, 0x0070, A1, SXTAB),

	ARMv7_OP4(0xfff0, 0xf0c0, 0xfa20, 0xf080, T1, SXTAB16),
	ARMv7_OP4(0x0ff0, 0x03f0, 0x0680, 0x0070, A1, SXTAB16),

	ARMv7_OP4(0xfff0, 0xf0c0, 0xfa00, 0xf080, T1, SXTAH),
	ARMv7_OP4(0x0ff0, 0x03f0, 0x06b0, 0x0070, A1, SXTAH),

	ARMv7_OP2(0xffc0, 0xb240, T1, SXTB),
	ARMv7_OP4(0xffff, 0xf0c0, 0xfa4f, 0xf080, T2, SXTB),
	ARMv7_OP4(0x0fff, 0x03f0, 0x06af, 0x0070, A1, SXTB),

	ARMv7_OP4(0xffff, 0xf0c0, 0xfa2f, 0xf080, T1, SXTB16),
	ARMv7_OP4(0x0fff, 0x03f0, 0x068f, 0x0070, A1, SXTB16),

	ARMv7_OP2(0xffc0, 0xb200, T1, SXTH),
	ARMv7_OP4(0xffff, 0xf0c0, 0xfa0f, 0xf080, T2, SXTH),
	ARMv7_OP4(0x0fff, 0x03f0, 0x06bf, 0x0070, A1, SXTH),

	ARMv7_OP4(0xfff0, 0xffe0, 0xe8d0, 0xf000, T1, TB_),

	ARMv7_OP4(0xfbf0, 0x8f00, 0xf090, 0x0f00, T1, TEQ_IMM),
	ARMv7_OP4(0x0ff0, 0xf000, 0x0330, 0x0000, A1, TEQ_IMM),
	ARMv7_OP4(0xfff0, 0x8f00, 0xea90, 0x0f00, T1, TEQ_REG),
	ARMv7_OP4(0x0ff0, 0xf010, 0x0130, 0x0000, A1, TEQ_REG),
	ARMv7_OP4(0x0ff0, 0xf090, 0x0130, 0x0010, A1, TEQ_RSR),

	ARMv7_OP4(0xfbf0, 0x8f00, 0xf010, 0x0f00, T1, TST_IMM),
	ARMv7_OP4(0x0ff0, 0xf000, 0x0310, 0x0000, A1, TST_IMM),
	ARMv7_OP2(0xffc0, 0x4200, T1, TST_REG),
	ARMv7_OP4(0xfff0, 0x8f00, 0xea10, 0x0f00, T2, TST_REG),
	ARMv7_OP4(0x0ff0, 0xf010, 0x0110, 0x0000, A1, TST_REG),
	ARMv7_OP4(0x0ff0, 0xf090, 0x0110, 0x0010, A1, TST_RSR),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfa90, 0xf040, T1, UADD16),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0650, 0x0f10, A1, UADD16),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfa80, 0xf040, T1, UADD8),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0650, 0x0f90, A1, UADD8),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfaa0, 0xf040, T1, UASX),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0650, 0x0f30, A1, UASX),

	ARMv7_OP4(0xfff0, 0x8020, 0xf3c0, 0x0000, T1, UBFX),
	ARMv7_OP4(0x0fe0, 0x0070, 0x07e0, 0x0050, A1, UBFX),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfbb0, 0xf0f0, T1, UDIV), // ???

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfa90, 0xf060, T1, UHADD16),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0670, 0x0f10, A1, UHADD16),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfa80, 0xf060, T1, UHADD8),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0670, 0x0f90, A1, UHADD8),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfaa0, 0xf060, T1, UHASX),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0670, 0x0f30, A1, UHASX),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfae0, 0xf060, T1, UHSAX),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0670, 0x0f50, A1, UHSAX),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfad0, 0xf060, T1, UHSUB16),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0670, 0x0f70, A1, UHSUB16),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfac0, 0xf060, T1, UHSUB8),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0670, 0x0ff0, A1, UHSUB8),

	ARMv7_OP4(0xfff0, 0x00f0, 0xfbe0, 0x0060, T1, UMAAL),
	ARMv7_OP4(0x0ff0, 0x00f0, 0x0040, 0x0090, A1, UMAAL),

	ARMv7_OP4(0xfff0, 0x00f0, 0xfbe0, 0x0000, T1, UMLAL),
	ARMv7_OP4(0x0fe0, 0x00f0, 0x00a0, 0x0090, A1, UMLAL),

	ARMv7_OP4(0xfff0, 0x00f0, 0xfba0, 0x0000, T1, UMULL),
	ARMv7_OP4(0x0fe0, 0x00f0, 0x0080, 0x0090, A1, UMULL),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfa90, 0xf050, T1, UQADD16),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0660, 0x0f10, A1, UQADD16),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfa80, 0xf050, T1, UQADD8),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0660, 0x0f90, A1, UQADD8),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfaa0, 0xf050, T1, UQASX),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0660, 0x0f30, A1, UQASX),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfae0, 0xf050, T1, UQSAX),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0660, 0x0f50, A1, UQSAX),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfad0, 0xf050, T1, UQSUB16),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0660, 0x0f70, A1, UQSUB16),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfac0, 0xf050, T1, UQSUB8),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0660, 0x0ff0, A1, UQSUB8),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfb70, 0xf000, T1, USAD8),
	ARMv7_OP4(0x0ff0, 0xf0f0, 0x0780, 0xf010, A1, USAD8),

	ARMv7_OP4(0xfff0, 0x00f0, 0xfb70, 0x0000, T1, USADA8),
	ARMv7_OP4(0x0ff0, 0x00f0, 0x0780, 0x0010, A1, USADA8),

	ARMv7_OP4(0xffd0, 0x8020, 0xf380, 0x0000, T1, USAT),
	ARMv7_OP4(0x0fe0, 0x0030, 0x06e0, 0x0010, A1, USAT),

	ARMv7_OP4(0xfff0, 0xf0e0, 0xf3a0, 0x0000, T1, USAT16),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x06e0, 0x0f30, A1, USAT16),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfae0, 0xf040, T1, USAX),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0650, 0x0f50, A1, USAX),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfad0, 0xf040, T1, USUB16),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0650, 0x0f70, A1, USUB16),

	ARMv7_OP4(0xfff0, 0xf0f0, 0xfac0, 0xf040, T1, USUB8),
	ARMv7_OP4(0x0ff0, 0x0ff0, 0x0650, 0x0ff0, A1, USUB8),

	ARMv7_OP4(0xfff0, 0xf0c0, 0xfa50, 0xf080, T1, UXTAB, SKIP_IF( BF(16, 19) == 15 )),
	ARMv7_OP4(0x0ff0, 0x03f0, 0x06e0, 0x0070, A1, UXTAB, SKIP_IF( BF(16, 19) == 15 )),

	ARMv7_OP4(0xfff0, 0xf0c0, 0xfa30, 0xf080, T1, UXTAB16),
	ARMv7_OP4(0x0ff0, 0x03f0, 0x06c0, 0x0070, A1, UXTAB16),

	ARMv7_OP4(0xfff0, 0xf0c0, 0xfa10, 0xf080, T1, UXTAH),
	ARMv7_OP4(0x0ff0, 0x03f0, 0x06f0, 0x0070, A1, UXTAH),

	ARMv7_OP2(0xffc0, 0xb2c0, T1, UXTB),
	ARMv7_OP4(0xffff, 0xf0c0, 0xfa5f, 0xf080, T2, UXTB),
	ARMv7_OP4(0x0fff, 0x03f0, 0x06ef, 0x0070, A1, UXTB),

	ARMv7_OP4(0xffff, 0xf0c0, 0xfa3f, 0xf080, T1, UXTB16),
	ARMv7_OP4(0x0fff, 0x03f0, 0x06cf, 0x0070, A1, UXTB16),

	ARMv7_OP2(0xffc0, 0xb280, T1, UXTH),
	ARMv7_OP4(0xffff, 0xf0c0, 0xfa1f, 0xf080, T2, UXTH),
	ARMv7_OP4(0x0fff, 0x03f0, 0x06ff, 0x0070, A1, UXTH),

	ARMv7_OP4(0xef80, 0x0f10, 0xef00, 0x0710, T1, VABA_),
	ARMv7_OP4(0xfe80, 0x0f10, 0xf200, 0x0710, A1, VABA_),
	ARMv7_OP4(0xef80, 0x0f50, 0xef80, 0x0500, T2, VABA_),
	ARMv7_OP4(0xfe80, 0x0f50, 0xf280, 0x0500, A2, VABA_),

	ARMv7_OP4(0xef80, 0x0f10, 0xef00, 0x0700, T1, VABD_),
	ARMv7_OP4(0xfe80, 0x0f10, 0xf200, 0x0700, A1, VABD_),
	ARMv7_OP4(0xef80, 0x0f50, 0xef80, 0x0700, T2, VABD_),
	ARMv7_OP4(0xfe80, 0x0f50, 0xf280, 0x0700, A2, VABD_),

	ARMv7_OP4(0xffa0, 0x0f10, 0xff20, 0x0d00, T1, VABD_FP),
	ARMv7_OP4(0xffa0, 0x0f10, 0xf320, 0x0d00, A1, VABD_FP),

	ARMv7_OP4(0xffb3, 0x0b90, 0xffb1, 0x0300, T1, VABS),
	ARMv7_OP4(0xffb3, 0x0b90, 0xf3b1, 0x0300, A1, VABS),
	ARMv7_OP4(0xffbf, 0x0ed0, 0xeeb0, 0x0ac0, T2, VABS),
	ARMv7_OP4(0x0fbf, 0x0ed0, 0x0eb0, 0x0ac0, A2, VABS),

	ARMv7_OP4(0xff80, 0x0f10, 0xff00, 0x0e10, T1, VAC__),
	ARMv7_OP4(0xff80, 0x0f10, 0xf300, 0x0e10, A1, VAC__),

	ARMv7_OP4(0xff80, 0x0f10, 0xef00, 0x0800, T1, VADD),
	ARMv7_OP4(0xff80, 0x0f10, 0xf200, 0x0800, A1, VADD),

	ARMv7_OP4(0xffa0, 0x0f10, 0xef00, 0x0d00, T1, VADD_FP),
	ARMv7_OP4(0xffa0, 0x0f10, 0xf200, 0x0d00, A1, VADD_FP),
	ARMv7_OP4(0xffb0, 0x0e50, 0xee30, 0x0a00, T2, VADD_FP),
	ARMv7_OP4(0x0fb0, 0x0e50, 0x0e30, 0x0a00, A2, VADD_FP),

	ARMv7_OP4(0xff80, 0x0f50, 0xef80, 0x0400, T1, VADDHN),
	ARMv7_OP4(0xff80, 0x0f50, 0xf280, 0x0400, A1, VADDHN),

	ARMv7_OP4(0xef80, 0x0e50, 0xef80, 0x0000, T1, VADD_),
	ARMv7_OP4(0xfe80, 0x0e50, 0xf280, 0x0000, A1, VADD_),

	ARMv7_OP4(0xffb0, 0x0f10, 0xef00, 0x0110, T1, VAND),
	ARMv7_OP4(0xffb0, 0x0f10, 0xf200, 0x0110, A1, VAND),

	ARMv7_OP4(0xefb8, 0x00b0, 0xef80, 0x0030, T1, VBIC_IMM),
	ARMv7_OP4(0xfeb0, 0x00b0, 0xf280, 0x0030, A1, VBIC_IMM),

	ARMv7_OP4(0xffb0, 0x0f10, 0xef10, 0x0110, T1, VBIC_REG),
	ARMv7_OP4(0xffb0, 0x0f10, 0xf210, 0x0110, A1, VBIC_REG),

	ARMv7_OP4(0xff80, 0x0f10, 0xff00, 0x0110, T1, VB__),
	ARMv7_OP4(0xff80, 0x0f10, 0xf300, 0x0110, A1, VB__),

	ARMv7_OP4(0xff80, 0x0f10, 0xff00, 0x0810, T1, VCEQ_REG),
	ARMv7_OP4(0xff80, 0x0f10, 0xf300, 0x0810, A1, VCEQ_REG),
	ARMv7_OP4(0xffa0, 0x0f10, 0xef00, 0x0e00, T2, VCEQ_REG),
	ARMv7_OP4(0xffa0, 0x0f10, 0xf200, 0x0e00, A2, VCEQ_REG),

	ARMv7_OP4(0xffb3, 0x0b90, 0xffb1, 0x0100, T1, VCEQ_ZERO),
	ARMv7_OP4(0xffb3, 0x0b90, 0xf3b1, 0x0100, A1, VCEQ_ZERO),

	ARMv7_OP4(0xef80, 0x0f10, 0xef00, 0x0310, T1, VCGE_REG),
	ARMv7_OP4(0xfe80, 0x0f10, 0xf200, 0x0310, A1, VCGE_REG),
	ARMv7_OP4(0xffa0, 0x0f10, 0xff00, 0x0e00, T2, VCGE_REG),
	ARMv7_OP4(0xffa0, 0x0f10, 0xf300, 0x0e00, A2, VCGE_REG),

	ARMv7_OP4(0xffb3, 0x0b90, 0xffb1, 0x0080, T1, VCGE_ZERO),
	ARMv7_OP4(0xffb3, 0x0b90, 0xf3b1, 0x0080, A1, VCGE_ZERO),

	ARMv7_OP4(0xef80, 0x0f10, 0xef00, 0x0300, T1, VCGT_REG),
	ARMv7_OP4(0xfe80, 0x0f10, 0xf200, 0x0300, A1, VCGT_REG),
	ARMv7_OP4(0xffa0, 0x0f10, 0xff20, 0x0e00, T2, VCGT_REG),
	ARMv7_OP4(0xffa0, 0x0f10, 0xf320, 0x0e00, A2, VCGT_REG),

	ARMv7_OP4(0xffb3, 0x0b90, 0xffb1, 0x0000, T1, VCGT_ZERO),
	ARMv7_OP4(0xffb3, 0x0b90, 0xf3b1, 0x0000, A1, VCGT_ZERO),

	ARMv7_OP4(0xffb3, 0x0b90, 0xffb1, 0x0180, T1, VCLE_ZERO),
	ARMv7_OP4(0xffb3, 0x0b90, 0xf3b1, 0x0180, A1, VCLE_ZERO),

	ARMv7_OP4(0xffb3, 0x0f90, 0xffb0, 0x0400, T1, VCLS),
	ARMv7_OP4(0xffb3, 0x0f90, 0xf3b0, 0x0400, A1, VCLS),

	ARMv7_OP4(0xffb3, 0x0b90, 0xffb1, 0x0200, T1, VCLT_ZERO),
	ARMv7_OP4(0xffb3, 0x0b90, 0xf3b1, 0x0200, A1, VCLT_ZERO),

	ARMv7_OP4(0xffb3, 0x0f90, 0xffb0, 0x0480, T1, VCLZ),
	ARMv7_OP4(0xffb3, 0x0f90, 0xf3b0, 0x0480, A1, VCLZ),

	ARMv7_OP4(0xffbf, 0x0e50, 0xeeb4, 0x0a40, T1, VCMP_),
	ARMv7_OP4(0x0fbf, 0x0e50, 0x0eb4, 0x0a40, A1, VCMP_),
	ARMv7_OP4(0xffbf, 0x0e7f, 0xeeb5, 0x0a40, T2, VCMP_),
	ARMv7_OP4(0x0fbf, 0x0e7f, 0x0eb5, 0x0a40, A2, VCMP_),

	ARMv7_OP4(0xffb3, 0x0f90, 0xffb0, 0x0500, T1, VCNT),
	ARMv7_OP4(0xffb3, 0x0f90, 0xf3b0, 0x0500, A1, VCNT),

	ARMv7_OP4(0xffb3, 0x0e10, 0xffb3, 0x0600, T1, VCVT_FIA),
	ARMv7_OP4(0xffb3, 0x0e10, 0xf3b3, 0x0600, A1, VCVT_FIA),

	ARMv7_OP4(0xffb8, 0x0e50, 0xeeb8, 0x0a40, T1, VCVT_FIF),
	ARMv7_OP4(0x0fb8, 0x0e50, 0x0eb8, 0x0a40, A1, VCVT_FIF),

	ARMv7_OP4(0xef80, 0x0e90, 0xef80, 0x0e10, T1, VCVT_FFA),
	ARMv7_OP4(0xfe80, 0x0e90, 0xf280, 0x0e10, A1, VCVT_FFA),

	ARMv7_OP4(0xffba, 0x0e50, 0xeeba, 0x0a40, T1, VCVT_FFF),
	ARMv7_OP4(0x0fba, 0x0e50, 0x0eba, 0x0a40, A1, VCVT_FFF),

	ARMv7_OP4(0xffbf, 0x0ed0, 0xeeb7, 0x0ac0, T1, VCVT_DF),
	ARMv7_OP4(0x0fbf, 0x0ed0, 0x0eb7, 0x0ac0, A1, VCVT_DF),

	ARMv7_OP4(0xffb3, 0x0ed0, 0xffb2, 0x0600, T1, VCVT_HFA),
	ARMv7_OP4(0xffb3, 0x0ed0, 0xf3b2, 0x0600, A1, VCVT_HFA),

	ARMv7_OP4(0xffbe, 0x0f50, 0xeeb2, 0x0a40, T1, VCVT_HFF),
	ARMv7_OP4(0x0fbe, 0x0f50, 0x0eb2, 0x0a40, A1, VCVT_HFF),

	ARMv7_OP4(0xffb0, 0x0e50, 0xee80, 0x0a00, T1, VDIV),
	ARMv7_OP4(0x0fb0, 0x0e50, 0x0e80, 0x0a00, A1, VDIV),

	ARMv7_OP4(0xffb0, 0x0f90, 0xffb0, 0x0c00, T1, VDUP_S),
	ARMv7_OP4(0xffb0, 0x0f90, 0xf3b0, 0x0c00, A1, VDUP_S),

	ARMv7_OP4(0xff90, 0x0f5f, 0xee80, 0x0b10, T1, VDUP_R),
	ARMv7_OP4(0x0f90, 0x0f5f, 0x0e80, 0x0b10, A1, VDUP_R),

	ARMv7_OP4(0xffb0, 0x0f10, 0xff00, 0x0110, T1, VEOR),
	ARMv7_OP4(0xffb0, 0x0f10, 0xf300, 0x0110, A1, VEOR),

	ARMv7_OP4(0xffb0, 0x0010, 0xefb0, 0x0000, T1, VEXT),
	ARMv7_OP4(0xffb0, 0x0010, 0xf2b0, 0x0000, A1, VEXT),

	ARMv7_OP4(0xef80, 0x0b10, 0xef00, 0x0000, T1, VHADDSUB),
	ARMv7_OP4(0xfe80, 0x0b10, 0xf200, 0x0000, A1, VHADDSUB),

	ARMv7_OP4(0xffb0, 0x0000, 0xf920, 0x0000, T1, VLD__MS), // VLD1, VLD2, VLD3, VLD4
	ARMv7_OP4(0xffb0, 0x0000, 0xf420, 0x0000, A1, VLD__MS),

	ARMv7_OP4(0xffb0, 0x0f00, 0xf9a0, 0x0c00, T1, VLD1_SAL),
	ARMv7_OP4(0xffb0, 0x0f00, 0xf4a0, 0x0c00, A1, VLD1_SAL),

	ARMv7_OP4(0xffb0, 0x0300, 0xf9a0, 0x0000, T1, VLD1_SL),
	ARMv7_OP4(0xffb0, 0x0300, 0xf4a0, 0x0000, A1, VLD1_SL),

	ARMv7_OP4(0xffb0, 0x0f00, 0xf9a0, 0x0d00, T1, VLD2_SAL),
	ARMv7_OP4(0xffb0, 0x0f00, 0xf4a0, 0x0d00, A1, VLD2_SAL),

	ARMv7_OP4(0xffb0, 0x0300, 0xf9a0, 0x0100, T1, VLD2_SL),
	ARMv7_OP4(0xffb0, 0x0300, 0xf4a0, 0x0100, A1, VLD2_SL),

	ARMv7_OP4(0xffb0, 0x0f00, 0xf9a0, 0x0e00, T1, VLD3_SAL),
	ARMv7_OP4(0xffb0, 0x0f00, 0xf4a0, 0x0e00, A1, VLD3_SAL),

	ARMv7_OP4(0xffb0, 0x0300, 0xf9a0, 0x0200, T1, VLD3_SL),
	ARMv7_OP4(0xffb0, 0x0300, 0xf4a0, 0x0200, A1, VLD3_SL),

	ARMv7_OP4(0xffb0, 0x0f00, 0xf9a0, 0x0f00, T1, VLD4_SAL),
	ARMv7_OP4(0xffb0, 0x0f00, 0xf4a0, 0x0f00, A1, VLD4_SAL),

	ARMv7_OP4(0xffb0, 0x0300, 0xf9a0, 0x0300, T1, VLD4_SL),
	ARMv7_OP4(0xffb0, 0x0300, 0xf4a0, 0x0300, A1, VLD4_SL),

	ARMv7_OP4(0xfe10, 0x0f00, 0xec10, 0x0b00, T1, VLDM),
	ARMv7_OP4(0x0e10, 0x0f00, 0x0c10, 0x0b00, A1, VLDM),
	ARMv7_OP4(0xfe10, 0x0f00, 0xec10, 0x0a00, T2, VLDM),
	ARMv7_OP4(0x0e10, 0x0f00, 0x0c10, 0x0a00, A2, VLDM),

	ARMv7_OP4(0xff30, 0x0f00, 0xed10, 0x0b00, T1, VLDR),
	ARMv7_OP4(0x0f30, 0x0f00, 0x0d10, 0x0b00, A1, VLDR),
	ARMv7_OP4(0xff30, 0x0f00, 0xed10, 0x0a00, T2, VLDR),
	ARMv7_OP4(0x0f30, 0x0f00, 0x0d10, 0x0a00, A2, VLDR),

	ARMv7_OP4(0xef80, 0x0f00, 0xef00, 0x0600, T1, VMAXMIN),
	ARMv7_OP4(0xfe80, 0x0f00, 0xf200, 0x0600, A1, VMAXMIN),

	ARMv7_OP4(0xff80, 0x0f10, 0xef00, 0x0f00, T1, VMAXMIN_FP),
	ARMv7_OP4(0xff80, 0x0f10, 0xf200, 0x0f00, A1, VMAXMIN_FP),

	ARMv7_OP4(0xef80, 0x0f10, 0xef00, 0x0900, T1, VML__),
	ARMv7_OP4(0xfe80, 0x0f10, 0xf200, 0x0900, A1, VML__),
	ARMv7_OP4(0xef80, 0x0d50, 0xef80, 0x0800, T2, VML__),
	ARMv7_OP4(0xfe80, 0x0d50, 0xf280, 0x0800, A2, VML__),

	ARMv7_OP4(0xff80, 0x0f10, 0xef00, 0x0d10, T1, VML__FP),
	ARMv7_OP4(0xff80, 0x0f10, 0xf200, 0x0d10, A1, VML__FP),
	ARMv7_OP4(0xffb0, 0x0e10, 0xee00, 0x0a00, T2, VML__FP),
	ARMv7_OP4(0x0fb0, 0x0e10, 0x0e00, 0x0a00, A2, VML__FP),

	ARMv7_OP4(0xef80, 0x0a50, 0xef80, 0x0040, T1, VML__S),
	ARMv7_OP4(0xfe80, 0x0a50, 0xf280, 0x0040, A1, VML__S),
	ARMv7_OP4(0xef80, 0x0b50, 0xef80, 0x0240, T2, VML__S),
	ARMv7_OP4(0xfe80, 0x0b50, 0xf280, 0x0240, A2, VML__S),

	ARMv7_OP4(0xefb8, 0x0090, 0xef80, 0x0010, T1, VMOV_IMM),
	ARMv7_OP4(0xfeb8, 0x0090, 0xf280, 0x0010, A1, VMOV_IMM),
	ARMv7_OP4(0xffb0, 0x0ef0, 0xeeb0, 0x0a00, T2, VMOV_IMM),
	ARMv7_OP4(0x0fb0, 0x0ef0, 0x0eb0, 0x0a00, A2, VMOV_IMM),

	ARMv7_OP4(0xffb0, 0x0f10, 0xef20, 0x0110, T1, VMOV_REG),
	ARMv7_OP4(0xffb0, 0x0f10, 0xf220, 0x0110, A1, VMOV_REG),
	ARMv7_OP4(0xffbf, 0x0ed0, 0xeeb0, 0x0a40, T2, VMOV_REG),
	ARMv7_OP4(0x0fbf, 0x0ed0, 0x0eb0, 0x0a40, A2, VMOV_REG),

	ARMv7_OP4(0xff90, 0x0f1f, 0xee00, 0x0b10, T1, VMOV_RS),
	ARMv7_OP4(0x0f90, 0x0f1f, 0x0e00, 0x0b10, A1, VMOV_RS),

	ARMv7_OP4(0xff10, 0x0f1f, 0xee10, 0x0b10, T1, VMOV_SR),
	ARMv7_OP4(0x0f10, 0x0f1f, 0x0e10, 0x0b10, A1, VMOV_SR),

	ARMv7_OP4(0xffe0, 0x0f7f, 0xee00, 0x0a10, T1, VMOV_RF),
	ARMv7_OP4(0x0fe0, 0x0f7f, 0x0e00, 0x0a10, A1, VMOV_RF),

	ARMv7_OP4(0xffe0, 0x0fd0, 0xec40, 0x0a10, T1, VMOV_2RF),
	ARMv7_OP4(0x0fe0, 0x0fd0, 0x0c40, 0x0a10, A1, VMOV_2RF),

	ARMv7_OP4(0xffe0, 0x0fd0, 0xec40, 0x0b10, T1, VMOV_2RD),
	ARMv7_OP4(0x0fe0, 0x0fd0, 0x0c40, 0x0b10, A1, VMOV_2RD),
	
	ARMv7_OP4(0xef87, 0x0fd0, 0xef80, 0x0a10, T1, VMOVL),
	ARMv7_OP4(0xfe87, 0x0fd0, 0xf280, 0x0a10, A1, VMOVL),

	ARMv7_OP4(0xffb3, 0x0fd0, 0xffb2, 0x0200, T1, VMOVN),
	ARMv7_OP4(0xffb3, 0x0fd0, 0xf3b2, 0x0200, A1, VMOVN),

	ARMv7_OP4(0xffff, 0x0fff, 0xeef1, 0x0a10, T1, VMRS),
	ARMv7_OP4(0x0fff, 0x0fff, 0x0ef1, 0x0a10, A1, VMRS),

	ARMv7_OP4(0xffff, 0x0fff, 0xeee1, 0x0a10, T1, VMSR),
	ARMv7_OP4(0x0fff, 0x0fff, 0x0ee1, 0x0a10, A1, VMSR),

	ARMv7_OP4(0xef80, 0x0f10, 0xef00, 0x0910, T1, VMUL_),
	ARMv7_OP4(0xfe80, 0x0f10, 0xf200, 0x0910, A1, VMUL_),
	ARMv7_OP4(0xef80, 0x0d50, 0xef80, 0x0c00, T2, VMUL_),
	ARMv7_OP4(0xfe80, 0x0d50, 0xf280, 0x0c00, A2, VMUL_),

	ARMv7_OP4(0xffa0, 0x0f10, 0xff00, 0x0d10, T1, VMUL_FP),
	ARMv7_OP4(0xffa0, 0x0f10, 0xf300, 0x0d10, A1, VMUL_FP),
	ARMv7_OP4(0xffb0, 0x0e50, 0xee20, 0x0a00, T2, VMUL_FP),
	ARMv7_OP4(0x0fb0, 0x0e50, 0x0e20, 0x0a00, A2, VMUL_FP),

	ARMv7_OP4(0xef80, 0x0e50, 0xef80, 0x0840, T1, VMUL_S),
	ARMv7_OP4(0xfe80, 0x0e50, 0xf280, 0x0840, A1, VMUL_S),
	ARMv7_OP4(0xef80, 0x0f50, 0xef80, 0x0a40, T2, VMUL_S),
	ARMv7_OP4(0xfe80, 0x0f50, 0xf280, 0x0a40, A2, VMUL_S),

	ARMv7_OP4(0xefb8, 0x00b0, 0xef80, 0x0030, T1, VMVN_IMM),
	ARMv7_OP4(0xfeb8, 0x00b0, 0xf280, 0x0030, A1, VMVN_IMM),

	ARMv7_OP4(0xffb3, 0x0f90, 0xffb0, 0x0580, T1, VMVN_REG),
	ARMv7_OP4(0xffb3, 0x0f90, 0xf3b0, 0x0580, A1, VMVN_REG),

	ARMv7_OP4(0xffb3, 0x0b90, 0xffb1, 0x0380, T1, VNEG),
	ARMv7_OP4(0xffb3, 0x0b90, 0xf3b1, 0x0380, A1, VNEG),
	ARMv7_OP4(0xffbf, 0x0ed0, 0xeeb1, 0x0a40, T2, VNEG),
	ARMv7_OP4(0x0fbf, 0x0ed0, 0x0eb1, 0x0a40, A2, VNEG),

	ARMv7_OP4(0xffb0, 0x0e10, 0xee10, 0x0a00, T1, VNM__),
	ARMv7_OP4(0x0fb0, 0x0e10, 0x0e10, 0x0a00, A1, VNM__),
	ARMv7_OP4(0xffb0, 0x0e50, 0xee20, 0x0a40, T2, VNM__),
	ARMv7_OP4(0x0fb0, 0x0e50, 0x0e20, 0x0a40, A2, VNM__),

	ARMv7_OP4(0xffb0, 0x0f10, 0xef30, 0x0110, T1, VORN_REG),
	ARMv7_OP4(0xffb0, 0x0f10, 0xf230, 0x0110, A1, VORN_REG),

	ARMv7_OP4(0xefb8, 0x00b0, 0xef80, 0x0010, T1, VORR_IMM),
	ARMv7_OP4(0xfeb8, 0x00b0, 0xf280, 0x0010, A1, VORR_IMM),

	ARMv7_OP4(0xffb0, 0x0f10, 0xef20, 0x0110, T1, VORR_REG),
	ARMv7_OP4(0xffb0, 0x0f10, 0xf220, 0x0110, A1, VORR_REG),

	ARMv7_OP4(0xffb3, 0x0f10, 0xffb0, 0x0600, T1, VPADAL),
	ARMv7_OP4(0xffb3, 0x0f10, 0xf3b0, 0x0600, A1, VPADAL),

	ARMv7_OP4(0xff80, 0x0f10, 0xef00, 0x0b10, T1, VPADD),
	ARMv7_OP4(0xff80, 0x0f10, 0xf200, 0x0b10, A1, VPADD),

	ARMv7_OP4(0xffa0, 0x0f10, 0xff00, 0x0d00, T1, VPADD_FP),
	ARMv7_OP4(0xffa0, 0x0f10, 0xf300, 0x0d00, A1, VPADD_FP),

	ARMv7_OP4(0xffb3, 0x0f10, 0xffb0, 0x0200, T1, VPADDL),
	ARMv7_OP4(0xffb3, 0x0f10, 0xf3b0, 0x0200, A1, VPADDL),

	ARMv7_OP4(0xef80, 0x0f00, 0xef00, 0x0a00, T1, VPMAXMIN),
	ARMv7_OP4(0xfe80, 0x0f00, 0xf200, 0x0a00, A1, VPMAXMIN),

	ARMv7_OP4(0xff80, 0x0f10, 0xff00, 0x0f00, T1, VPMAXMIN_FP),
	ARMv7_OP4(0xff80, 0x0f10, 0xf300, 0x0f00, A1, VPMAXMIN_FP),

	ARMv7_OP4(0xffbf, 0x0f00, 0xecbd, 0x0b00, T1, VPOP),
	ARMv7_OP4(0x0fbf, 0x0f00, 0x0cbd, 0x0b00, A1, VPOP),
	ARMv7_OP4(0xffbf, 0x0f00, 0xecbd, 0x0a00, T2, VPOP),
	ARMv7_OP4(0x0fbf, 0x0f00, 0x0cbd, 0x0a00, A2, VPOP),

	ARMv7_OP4(0xffbf, 0x0f00, 0xed2d, 0x0b00, T1, VPUSH),
	ARMv7_OP4(0x0fbf, 0x0f00, 0x0d2d, 0x0b00, A1, VPUSH),
	ARMv7_OP4(0xffbf, 0x0f00, 0xed2d, 0x0a00, T2, VPUSH),
	ARMv7_OP4(0x0fbf, 0x0f00, 0x0d2d, 0x0a00, A2, VPUSH),

	// TODO: VQ* instructions

	ARMv7_OP4(0xff80, 0x0f50, 0xff80, 0x0400, T1, VRADDHN),
	ARMv7_OP4(0xff80, 0x0f50, 0xf380, 0x0400, A1, VRADDHN),

	ARMv7_OP4(0xffb3, 0x0e90, 0xffb3, 0x0400, T1, VRECPE),
	ARMv7_OP4(0xffb3, 0x0e90, 0xf3b3, 0x0400, A1, VRECPE),

	ARMv7_OP4(0xffa0, 0x0f10, 0xef00, 0x0f10, T1, VRECPS),
	ARMv7_OP4(0xffa0, 0x0f10, 0xf200, 0x0f10, A1, VRECPS),

	ARMv7_OP4(0xffb3, 0x0e10, 0xffb0, 0x0000, T1, VREV__),
	ARMv7_OP4(0xffb3, 0x0e10, 0xf3b0, 0x0000, A1, VREV__),

	ARMv7_OP4(0xef80, 0x0f10, 0xef00, 0x0100, T1, VRHADD),
	ARMv7_OP4(0xfe80, 0x0f10, 0xf200, 0x0100, A1, VRHADD),

	ARMv7_OP4(0xef80, 0x0f10, 0xef00, 0x0500, T1, VRSHL),
	ARMv7_OP4(0xfe80, 0x0f10, 0xf200, 0x0500, A1, VRSHL),

	ARMv7_OP4(0xef80, 0x0f10, 0xef80, 0x0210, T1, VRSHR),
	ARMv7_OP4(0xfe80, 0x0f10, 0xf280, 0x0210, A1, VRSHR),

	ARMv7_OP4(0xff80, 0x0fd0, 0xef80, 0x0850, T1, VRSHRN),
	ARMv7_OP4(0xff80, 0x0fd0, 0xf280, 0x0850, A1, VRSHRN),

	ARMv7_OP4(0xffb3, 0x0e90, 0xffb3, 0x0480, T1, VRSQRTE),
	ARMv7_OP4(0xffb3, 0x0e90, 0xf3b3, 0x0480, A1, VRSQRTE),

	ARMv7_OP4(0xffa0, 0x0f10, 0xef20, 0x0f10, T1, VRSQRTS),
	ARMv7_OP4(0xffa0, 0x0f10, 0xf220, 0x0f10, A1, VRSQRTS),

	ARMv7_OP4(0xef80, 0x0f10, 0xef80, 0x0310, T1, VRSRA),
	ARMv7_OP4(0xfe80, 0x0f10, 0xf280, 0x0310, A1, VRSRA),

	ARMv7_OP4(0xff80, 0x0f50, 0xff80, 0x0600, T1, VRSUBHN),
	ARMv7_OP4(0xff80, 0x0f50, 0xf380, 0x0600, A1, VRSUBHN),

	ARMv7_OP4(0xff80, 0x0f10, 0xef80, 0x0510, T1, VSHL_IMM),
	ARMv7_OP4(0xff80, 0x0f10, 0xf280, 0x0510, A1, VSHL_IMM),

	ARMv7_OP4(0xef80, 0x0f10, 0xef00, 0x0400, T1, VSHL_REG),
	ARMv7_OP4(0xfe80, 0x0f10, 0xf200, 0x0400, A1, VSHL_REG),

	ARMv7_OP4(0xef80, 0x0fd0, 0xef80, 0x0a10, T1, VSHLL),
	ARMv7_OP4(0xfe80, 0x0fd0, 0xf280, 0x0a10, A1, VSHLL),
	ARMv7_OP4(0xffb3, 0x0fd0, 0xffb2, 0x0300, T2, VSHLL),
	ARMv7_OP4(0xffb3, 0x0fd0, 0xf3b2, 0x0300, A2, VSHLL),

	ARMv7_OP4(0xef80, 0x0f10, 0xef80, 0x0010, T1, VSHR),
	ARMv7_OP4(0xfe80, 0x0f10, 0xf280, 0x0010, A1, VSHR),
	
	ARMv7_OP4(0xff80, 0x0fd0, 0xef80, 0x0810, T1, VSHRN),
	ARMv7_OP4(0xff80, 0x0fd0, 0xf280, 0x0810, A1, VSHRN),

	ARMv7_OP4(0xff80, 0x0f10, 0xff80, 0x0510, T1, VSLI),
	ARMv7_OP4(0xff80, 0x0f10, 0xf380, 0x0510, A1, VSLI),

	ARMv7_OP4(0xffbf, 0x0ed0, 0xeeb1, 0x0ac0, T1, VSQRT),
	ARMv7_OP4(0x0fbf, 0x0ed0, 0x0eb1, 0x0ac0, A1, VSQRT),

	ARMv7_OP4(0xef80, 0x0f10, 0xef80, 0x0110, T1, VSRA),
	ARMv7_OP4(0xfe80, 0x0f10, 0xf280, 0x0110, A1, VSRA),

	ARMv7_OP4(0xff80, 0x0f10, 0xff80, 0x0410, T1, VSRI),
	ARMv7_OP4(0xff80, 0x0f10, 0xf380, 0x0410, A1, VSRI),

	ARMv7_OP4(0xffb0, 0x0000, 0xf900, 0x0000, T1, VST__MS), // VST1, VST2, VST3, VST4
	ARMv7_OP4(0xffb0, 0x0000, 0xf400, 0x0000, A1, VST__MS),

	ARMv7_OP4(0xffb0, 0x0300, 0xf980, 0x0000, T1, VST1_SL),
	ARMv7_OP4(0xffb0, 0x0300, 0xf480, 0x0000, A1, VST1_SL),

	ARMv7_OP4(0xffb0, 0x0300, 0xf980, 0x0100, T1, VST2_SL),
	ARMv7_OP4(0xffb0, 0x0300, 0xf480, 0x0100, A1, VST2_SL),

	ARMv7_OP4(0xffb0, 0x0300, 0xf980, 0x0200, T1, VST3_SL),
	ARMv7_OP4(0xffb0, 0x0300, 0xf480, 0x0200, A1, VST3_SL),

	ARMv7_OP4(0xffb0, 0x0300, 0xf980, 0x0300, T1, VST4_SL),
	ARMv7_OP4(0xffb0, 0x0300, 0xf480, 0x0300, A1, VST4_SL),

	ARMv7_OP4(0xfe10, 0x0f00, 0xec00, 0x0b00, T1, VSTM),
	ARMv7_OP4(0x0e10, 0x0f00, 0x0c00, 0x0b00, A1, VSTM),
	ARMv7_OP4(0xfe10, 0x0f00, 0xec00, 0x0a00, T2, VSTM),
	ARMv7_OP4(0x0e10, 0x0f00, 0x0c00, 0x0a00, A2, VSTM),

	ARMv7_OP4(0xff30, 0x0f00, 0xed00, 0x0b00, T1, VSTR),
	ARMv7_OP4(0x0f30, 0x0f00, 0x0d00, 0x0b00, A1, VSTR),
	ARMv7_OP4(0xff30, 0x0f00, 0xed00, 0x0a00, T2, VSTR),
	ARMv7_OP4(0x0f30, 0x0f00, 0x0d00, 0x0a00, A2, VSTR),

	ARMv7_OP4(0xff80, 0x0f10, 0xff00, 0x0800, T1, VSUB),
	ARMv7_OP4(0xff80, 0x0f10, 0xf300, 0x0800, A1, VSUB),

	ARMv7_OP4(0xffa0, 0x0f10, 0xef20, 0x0d00, T1, VSUB_FP),
	ARMv7_OP4(0xffa0, 0x0f10, 0xf220, 0x0d00, A1, VSUB_FP),
	ARMv7_OP4(0xffb0, 0x0e50, 0xee30, 0x0a40, T2, VSUB_FP),
	ARMv7_OP4(0x0fb0, 0x0e50, 0x0e30, 0x0a40, A2, VSUB_FP),

	ARMv7_OP4(0xff80, 0x0f50, 0xef80, 0x0600, T1, VSUBHN),
	ARMv7_OP4(0xff80, 0x0f50, 0xf280, 0x0600, A1, VSUBHN),

	ARMv7_OP4(0xef80, 0x0e50, 0xef80, 0x0200, T1, VSUB_),
	ARMv7_OP4(0xfe80, 0x0e50, 0xf280, 0x0200, A1, VSUB_),

	ARMv7_OP4(0xffb3, 0x0f90, 0xffb2, 0x0000, T1, VSWP),
	ARMv7_OP4(0xffb3, 0x0f90, 0xf3b2, 0x0000, A1, VSWP),

	ARMv7_OP4(0xffb0, 0x0c10, 0xffb0, 0x0800, T1, VTB_),
	ARMv7_OP4(0xffb0, 0x0c10, 0xf3b0, 0x0800, A1, VTB_),

	ARMv7_OP4(0xffb3, 0x0f90, 0xffb2, 0x0080, T1, VTRN),
	ARMv7_OP4(0xffb3, 0x0f90, 0xf3b2, 0x0080, A1, VTRN),

	ARMv7_OP4(0xff80, 0x0f10, 0xef00, 0x0810, T1, VTST),
	ARMv7_OP4(0xff80, 0x0f10, 0xf200, 0x0810, A1, VTST),

	ARMv7_OP4(0xffb3, 0x0f90, 0xffb2, 0x0100, T1, VUZP),
	ARMv7_OP4(0xffb3, 0x0f90, 0xf3b2, 0x0100, A1, VUZP),

	ARMv7_OP4(0xffb3, 0x0f90, 0xffb2, 0x0180, T1, VZIP),
	ARMv7_OP4(0xffb3, 0x0f90, 0xf3b2, 0x0180, A1, VZIP),

	ARMv7_OP2(0xffff, 0xbf20, T1, WFE),
	ARMv7_OP4(0xffff, 0xffff, 0xf3af, 0x8002, T2, WFE),
	ARMv7_OP4(0x0fff, 0xffff, 0x0320, 0xf002, A1, WFE),
	ARMv7_OP2(0xffff, 0xbf30, T1, WFI),
	ARMv7_OP4(0xffff, 0xffff, 0xf3af, 0x8003, T2, WFI),
	ARMv7_OP4(0x0fff, 0xffff, 0x0320, 0xf003, A1, WFI),
	ARMv7_OP2(0xffff, 0xbf10, T1, YIELD),
	ARMv7_OP4(0xffff, 0xffff, 0xf3af, 0x8001, T2, YIELD),
	ARMv7_OP4(0x0fff, 0xffff, 0x0320, 0xf001, A1, YIELD),
};

#undef ARMv7_OP2
#undef ARMv7_OP4
#undef SKIP_IF
#undef BF
#undef BT

struct ARMv7_op2_table_t
{
	const ARMv7_opcode_t* data[0x10000];
	u32 null_ops;

	ARMv7_op2_table_t()
	{
		std::vector<const ARMv7_opcode_t*> t2;

		for (auto& opcode : ARMv7_opcode_table)
		{
			if (opcode.length == 2)
			{
				if (opcode.code & ~opcode.mask)
				{
					LOG_ERROR(ARMv7, "%s: wrong opcode mask (mask=0x%04x, code=0x%04x)", opcode.name, opcode.mask >> 16, opcode.code >> 16);
				}

				t2.push_back(&opcode);
			}
		}

		null_ops = 0x10000;

		for (u32 i = 0; i < 0x10000; i++)
		{
			data[i] = nullptr;

			for (auto& opcode : t2)
			{
				if (((i << 16) & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(i)))
				{
					data[i] = opcode;
					null_ops--;
					break;
				}
			}
		}
	}

} g_op2t;

struct ARMv7_op4t_table_t
{
	std::vector<const ARMv7_opcode_t*> table;

	ARMv7_op4t_table_t()
	{
		for (auto& opcode : ARMv7_opcode_table)
		{
			if (opcode.length == 4 && opcode.type < A1)
			{
				if (opcode.code & ~opcode.mask)
				{
					LOG_ERROR(ARMv7, "%s: wrong opcode mask (mask=0x%04x 0x%04x, code=0x%04x 0x%04x)", opcode.name, opcode.mask >> 16, (u16)opcode.mask, opcode.code >> 16, (u16)opcode.code);
				}

				table.push_back(&opcode);
			}
		}
	}

	const ARMv7_opcode_t* HACK()
	{
		for (auto& opcode : table)
		{
			if (opcode->func == ARMv7_instrs::HACK)
			{
				return opcode;
			}
		}

		throw EXCEPTION("HACK instruction not found");
	}
	
} g_op4t;

struct ARMv7_op4arm_table_t
{
	std::vector<const ARMv7_opcode_t*> table;

	ARMv7_op4arm_table_t()
	{
		for (auto& opcode : ARMv7_opcode_table)
		{
			if (opcode.type >= A1)
			{
				if (opcode.code & ~opcode.mask)
				{
					LOG_ERROR(ARMv7, "%s: wrong opcode mask (mask=0x%08x, code=0x%08x)", opcode.name, opcode.mask, opcode.code);
				}

				table.push_back(&opcode);
			}
		}
	}

} g_op4arm;

std::unordered_map<u32, const ARMv7_opcode_t*> g_opct;

void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump)
{
	// 1. Find every 4-byte Thumb instruction and cache it
	// 2. If some instruction is not recognized, print the error
	// 3. Possibly print disasm

	//g_opct.clear();
	//g_opct.reserve(end_addr - addr);

	const auto hack = g_op4t.HACK();

	while (addr < end_addr)
	{
		ARMv7Code code = {};
		code.code0 = vm::psv::read16(addr);

		auto found = g_op2t.data[code.code0];

		if (!found)
		{
			code.code1 = code.code0;
			code.code0 = vm::psv::read16(addr + 2);

			auto op = g_opct.find(code.data);
			if (op != g_opct.end())
			{
				found = op->second;
			}
		}

		if (!found)
		{
			for (auto opcode : g_op4t.table)
			{
				if ((code.data & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(code.data)))
				{
					g_opct[code.data] = (found = opcode);
					break;
				}
			}
		}
		
		if (!found)
		{
			LOG_ERROR(ARMv7, "Unknown instruction found at address 0x%08x: %04x %04x", addr, code.code1, code.code0);
			addr += 4;
			continue;
		}
		
		// Proceed with found:

		if (dump)
		{
			if (found->length == 2)
			{
				LOG_NOTICE(ARMv7, "0x%08x: %04x       %s", addr, code.code0, found->name);
			}
			else
			{
				LOG_NOTICE(ARMv7, "0x%08x: %04x %04x  %s", addr, code.code1, code.code0, found->name);
			}
		}

		if (found->func == ARMv7_instrs::BLX && found->type == T2)
		{
			const u32 s = (code.data >> 26) & 0x1;
			const u32 i1 = (code.data >> 13) & 0x1 ^ s ^ 1;
			const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1;
			const u32 target = (addr + 4 & ~3) + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1);

			const u32 instr = vm::check_addr(target, 4) ? vm::psv::read32(target).value() : 0;

			// possibly a call to imported function:
			if (target >= end_addr && ((target - end_addr) % 16) == 0 && (instr & 0xfff000f0) == 0xe0700090)
			{
				// replace BLX with "HACK" instruction directly (in Thumb form), it can help to see where it was called from
				const u32 index = (instr & 0xfff00) >> 4 | (instr & 0xf);
				vm::psv::write32(addr, 0xf870 | index << 16);
				g_opct[0xf8700000 | index] = hack;
			}
			else
			{
				LOG_ERROR(ARMv7, "Unrecognized BLX call found at adddress 0x%08x (target=0x%08x)", addr, target);
			}
		}

		//if (found->func == ARMv7_instrs::IT)
		//{
		//	LOG_ERROR(ARMv7, "IT instruction found at address 0x%08x", addr);
		//}

		addr += found->length;
	}

	LOG_NOTICE(ARMv7, "armv7_decoder_initialize() finished, g_opct.size() = %lld, g_op2t.null_ops=0x%x", (u64)g_opct.size(), g_op2t.null_ops);
}

u32 ARMv7Decoder::DecodeMemory(const u32 address)
{
	ARMv7Code code = {};

	if (m_ctx.ISET == Thumb)
	{
		code.code0 = vm::psv::read16(address);

		if (auto opcode = g_op2t.data[code.code0])
		{
			(*opcode->func)(m_ctx, code, opcode->type);
			return 2;
		}

		code.code1 = code.code0;
		code.code0 = vm::psv::read16(address + 2);

		auto op = g_opct.find(code.data);
		if (op != g_opct.end())
		{
			(*op->second->func)(m_ctx, code, op->second->type);
			return 4;
		}

		//for (auto opcode : g_op4t.table)
		//{
		//	if ((code.data & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(code.data)))
		//	{
		//		(*opcode->func)(m_ctx, code, opcode->type);
		//		return 4;
		//	}
		//}
	}
	else if (m_ctx.ISET == ARM)
	{
		code.data = vm::psv::read32(address);

		for (auto opcode : g_op4arm.table)
		{
			if ((code.data & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(code.data)))
			{
				(*opcode->func)(m_ctx, code, opcode->type);
				return 4;
			}
		}
	}
	else
	{
		throw EXCEPTION("Invalid instruction set");
	}
	
	ARMv7_instrs::UNK(m_ctx, code);
	return 4;

	// "group" decoding algorithm (temporarily disabled)

	//execute_main_group(&m_thr);
	//// LOG_NOTICE(ARMv7, "%s, %d \n\n", m_thr.m_last_instr_name, m_thr.m_last_instr_size);
	//m_thr.m_last_instr_name = "Unknown";
	//return m_thr.m_last_instr_size;
}
